package cn.zzdt4j.console.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.zzdt4j.common.extension.enums.DelEnum;
import cn.zzdt4j.common.toolkit.DateUtil;
import cn.zzdt4j.config.mapper.ConfigInfoMapper;
import cn.zzdt4j.config.mapper.HisRunDataMapper;
import cn.zzdt4j.config.mapper.ItemInfoMapper;
import cn.zzdt4j.config.mapper.TenantInfoMapper;
import cn.zzdt4j.config.model.ConfigAllInfo;
import cn.zzdt4j.config.model.ConfigInfoBase;
import cn.zzdt4j.config.model.ItemInfo;
import cn.zzdt4j.config.model.TenantInfo;
import cn.zzdt4j.console.model.ChartInfo;
import cn.zzdt4j.console.model.LineChartInfo;
import cn.zzdt4j.console.model.PieChartInfo;
import cn.zzdt4j.console.model.TenantChart;
import cn.zzdt4j.console.service.DashboardService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * The type Dashboard service impl.
 *
 * @author by <a href="mailto:ligang941012@gmail.com">gang.Li</a>
 * @since 2023 /11/6 20:18
 */
@Service
@AllArgsConstructor
public class DashboardServiceImpl implements DashboardService {

    private final TenantInfoMapper tenantInfoMapper;

    private final ItemInfoMapper itemInfoMapper;

    private final ConfigInfoMapper configInfoMapper;

    private final HisRunDataMapper hisRunDataMapper;

    @Override
    public PieChartInfo getPieChart() {
        final LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class)
                .eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode())
                .select(ItemInfo::getItemId);
        List<Object> itemNameList = itemInfoMapper.selectObjs(itemQueryWrapper);
        List<Map<String, Object>> pieDataList = new ArrayList<>();
        for (Object each : itemNameList) {
            final LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
                    .eq(ConfigInfoBase::getItemId, each)
                    .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode());
            final Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
            if (threadPoolCount != null) {
                Map<String, Object> dict = new LinkedHashMap<>();
                dict.put("name", each);
                dict.put("value", threadPoolCount);
                pieDataList.add(dict);
            }
        }
        pieDataList.sort((one, two) -> (int) two.get("value") - (int) one.get("value"));
        List<String> resultItemIds = new ArrayList<>();
        List<Map<String, Object>> resultPieDataList = pieDataList.stream()
                .limit(5)
                .peek(each -> resultItemIds.add(each.get("name").toString())).collect(Collectors.toList());
        return new PieChartInfo(resultItemIds,resultPieDataList);
    }

    @Override
    public TenantChart getTenantChart() {
        List<Map<String, Object>> tenantChartList = new ArrayList<>();
        final List<TenantInfo> tenantInfos = tenantInfoMapper.selectList(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
        for (TenantInfo tenantInfo : tenantInfos) {
            int tenantThreadPoolNum = 0;
            final LambdaQueryWrapper<ItemInfo> itemQueryWrapper = Wrappers.lambdaQuery(ItemInfo.class)
                    .eq(ItemInfo::getTenantId, tenantInfo.getTenantId())
                    .eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode())
                    .select(ItemInfo::getItemId);
            final List<ItemInfo> itemInfos = itemInfoMapper.selectList(itemQueryWrapper);
            for (ItemInfo itemInfo : itemInfos) {
                final LambdaQueryWrapper<ConfigAllInfo> threadPoolQueryWrapper = Wrappers.lambdaQuery(ConfigAllInfo.class)
                        .eq(ConfigInfoBase::getItemId, itemInfo.getItemId())
                        .eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode());
                final Integer threadPoolCount = configInfoMapper.selectCount(threadPoolQueryWrapper);
                tenantThreadPoolNum += threadPoolCount;
            }
            Map<String, Object> dict = new LinkedHashMap<>();
            dict.put("name", tenantInfo.getTenantId());
            dict.put("value", tenantThreadPoolNum);
            tenantChartList.add(dict);
        }
        List<Map<String, Object>> resultTenantChartList = tenantChartList.stream()
                .sorted((one, two) -> (int) two.get("value") - (int) one.get("value"))
                .limit(5)
                .collect(Collectors.toList());
        return new TenantChart(resultTenantChartList);
    }

    @Override
    public LineChartInfo getLineChartInfo() {
        final LocalDateTime currentDate = LocalDateTime.now();
        final LocalDateTime startDate = currentDate.plusMinutes(-10);
        final long currentTime = DateUtil.getTime(currentDate);
        final long startTime = DateUtil.getTime(startDate);
        List<HisRunDataMapper.ThreadPoolTaskRanking> threadPoolTaskRankings = hisRunDataMapper.queryThreadPoolMaxRanking(startTime, currentTime);
        List<Object> oneList = new ArrayList<>();
        List<Object> twoList = new ArrayList<>();
        List<Object> threeList = new ArrayList<>();
        List<Object> fourList = new ArrayList<>();
        final ArrayList<List<Object>> lists = CollectionUtil.newArrayList(oneList, twoList, threeList, fourList);
        for (int i = 0; i < threadPoolTaskRankings.size(); i++) {
            final List<Object> eachList = lists.get(i);
            final HisRunDataMapper.ThreadPoolTaskRanking taskRanking = threadPoolTaskRankings.get(i);
            eachList.add(taskRanking.getTpId());
            eachList.add(taskRanking.getMaxQueueSize());
            eachList.add(taskRanking.getMaxRejectCount());
            eachList.add(taskRanking.getMaxCompletedTaskCount());
        }
        return new LineChartInfo(oneList, twoList, threeList, fourList);
    }

    @Override
    public ChartInfo getChartInfo() {
        final Integer tenantCount = tenantInfoMapper.selectCount(Wrappers.lambdaQuery(TenantInfo.class).eq(TenantInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
        final Integer itemCount = itemInfoMapper.selectCount(Wrappers.lambdaQuery(ItemInfo.class).eq(ItemInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
        final Integer threadPoolCount = configInfoMapper.selectCount(Wrappers.lambdaQuery(ConfigAllInfo.class).eq(ConfigAllInfo::getDelFlag, DelEnum.NORMAL.getIntCode()));
        ChartInfo chartInfo = new ChartInfo();
        chartInfo.setTenantCount(tenantCount)
                .setItemCount(itemCount)
                .setThreadPoolCount(threadPoolCount);
        // .setThreadPoolInstanceCount(ConfigCacheService)
        return chartInfo;
    }
}
